﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Controls;
using System.Diagnostics;

namespace WPFTurnBasedStrategyGame
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private static Piece pieceBeingPathed = null;
        private static GameTeam currentTeam = GameTeam.Red;
        private static GameTeam startingTeam = GameTeam.Red;
        private static int turnCount = 1;
        private static double movesLeft = 10.0;
        private static Random r = new Random();

        public MainWindow()
        {
            InitializeComponent();
            
            int a = r.Next(2);
            if (a == 1)
            {
                currentTeam = GameTeam.Blue;
            }
            else
            {
                currentTeam = GameTeam.Red;
            }
            TeamName.Content = currentTeam;
            startingTeam = currentTeam;
            MoveCount.Content = movesLeft;
            theWindow = this;
        }

        private void Piece_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = false;
        }

        private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {

            if (e.OriginalSource is Piece && pieceBeingPathed == null)
            {
                Piece temp = (Piece)e.OriginalSource;
                if (temp.Team != currentTeam)
                {
                    return;
                }
                pieceBeingPathed = temp;

                if (!moves.ContainsKey(pieceBeingPathed))
                {
                    moves.Add(pieceBeingPathed, new List<Gametangle>());
                }
                else
                {
                    // insert code to show path here;
                }
                ForEachControlRecursive(this);
                firstTimeThrough = false;
            }
            else if (e.OriginalSource is Gametangle && pieceBeingPathed != null)
            {

                if (moves[pieceBeingPathed].Count >= 2)
                {


                    GeometryConverter gc = new GeometryConverter();
                    List<PathFigure> figures = new List<PathFigure>();
                    List<PathSegment> segments = new List<PathSegment>();

                    foreach (Gametangle gt in moves[pieceBeingPathed])
                    {
                        LineSegment ls = new LineSegment(gt.TranslatePoint(new Point(5, 5), pieceBeingPathed), true);
                        segments.Add(ls);
                    }

                    figures.Add(new PathFigure(pieceBeingPathed.TranslatePoint(new Point(0, 0), pieceBeingPathed), segments, false));
                    PathGeometry pg = new PathGeometry(figures);

                    MatrixTransform xform = new MatrixTransform();
                    pieceBeingPathed.RenderTransform = xform;
                    MatrixAnimationUsingPath anima = new MatrixAnimationUsingPath();
                    anima.PathGeometry = pg;
                    anima.Duration = new Duration(TimeSpan.FromSeconds(5));
                    xform.BeginAnimation(MatrixTransform.MatrixProperty, anima);

                    moves[pieceBeingPathed][0].Pieces.Remove(pieceBeingPathed);
                    moves[pieceBeingPathed][moves[pieceBeingPathed].Count - 1].Pieces.Add(pieceBeingPathed);
                }

                pieceBeingPathed = null;

                ForEachControlRecursive(this);
                firstTimeThrough = false;
            }


        }

        private static bool firstTimeThrough = true;
        private static Dictionary<Piece, List<Gametangle>> moves = new Dictionary<Piece, List<Gametangle>>();
        private static Gametangle previousGametangle;
        private static MainWindow theWindow;
        private static StackPanel currentRow;  
        private static int currentRowCount = -1;
        private static int currentColumnCount = 0;
        private static Gametangle[,] map = new Gametangle[200,200];

        private static void ForEachControlRecursive(object root)
        {
            UIElement control = root as UIElement;

            if (control is Gametangle)
            {
                Gametangle gt = (Gametangle)control;
                if (firstTimeThrough)
                {
                    StackPanel sp = (StackPanel)gt.Parent;
                    if (sp != currentRow)
                    {
                        currentRowCount++;
                        currentColumnCount = 0;
                        currentRow = sp;
                    }
                    
                    gt.Y = currentRowCount;
                    gt.X = currentColumnCount++;

                    if (map[pieceBeingPathed.X, pieceBeingPathed.Y] == null)
                    {
                        map[pieceBeingPathed.X, pieceBeingPathed.Y] = new Gametangle();
                    }

                    if (map[gt.X, gt.Y] == null)
                    {
                        map[gt.X, gt.Y] = new Gametangle();
                    }

                    
                    gt.Pieces = map[gt.X, gt.Y].Pieces;                    
                    map[gt.X, gt.Y] = gt;

                    gt.Pathed += new RoutedEventHandler(gt_Pathed);
                }
                gt.ToggleRecordingMoves();
            }           
            
            if (control is Piece)
            {
                Piece p = (Piece)control;
                if (map[p.X, p.Y] == null)
                {
                    map[p.X, p.Y] = new Gametangle();                    
                }
                map[p.X, p.Y].Pieces.Add(p);
            }

            if (root is DependencyObject)
            {
                foreach (object child in LogicalTreeHelper.GetChildren((DependencyObject)root))
                {
                    ForEachControlRecursive(child);
                }
            }
        }

        

        static void gt_Pathed(object sender, RoutedEventArgs e)
        {
            Gametangle gt = (Gametangle)sender;
            double cost = 1;

            if (previousGametangle != null)
            {
                List<Piece> enemies = GetAdjoiningEnemies(previousGametangle.X, previousGametangle.Y, pieceBeingPathed);
                if (enemies.Count > 0)
                {
                    pieceBeingPathed.NeedsCombatResolution = enemies;
                    cost = 1000;
                }
                else
                {
                    BorderFeatureDirection bfd = ComputeDirectionOfMovement(previousGametangle, gt);
                    if (previousGametangle.HasFeatureInThisDirection(bfd, BorderFeatureType.Road) || gt.Terrain == LandType.City)
                    {
                        cost = .3;
                    }
                    if (gt.Terrain == LandType.Forest || previousGametangle.HasFeatureInThisDirection(bfd, BorderFeatureType.River))
                    {
                        cost = 2;
                    }
                }
            }                        

            if (movesLeft - cost < 0)
            {
                e.Handled = true;
                gt.CancelMove();
                return;
            }

            movesLeft -= cost;
            theWindow.MoveCount.Content = movesLeft;

            moves[pieceBeingPathed].Add(gt);
            previousGametangle = gt;
        }

        private static List<Piece> GetAdjoiningEnemies(int targetX, int targetY, Piece pieceUnderDiscussion)
        {
            List<Piece> lp = new List<Piece>();
            AddPieces(lp, targetX - 1, targetY - 1, pieceUnderDiscussion); // SouthWest
            AddPieces(lp, targetX - 1, targetY, pieceUnderDiscussion); // West
            AddPieces(lp, targetX - 1, targetY + 1, pieceUnderDiscussion); // NorthWest
            AddPieces(lp, targetX, targetY - 1, pieceUnderDiscussion); // South
            AddPieces(lp, targetX, targetY + 1, pieceUnderDiscussion); // North
            AddPieces(lp, targetX + 1, targetY - 1, pieceUnderDiscussion); //NorthEast
            AddPieces(lp, targetX + 1, targetY, pieceUnderDiscussion); //East
            AddPieces(lp, targetX + 1, targetY + 1, pieceUnderDiscussion); //SouthEast           
            return lp;
        }

        private static void AddPieces(List<Piece> lp, int x, int y, Piece pieceUnderDiscussion)
        {
            if (x >= 0 && y >= 00 && x <= map.GetUpperBound(0) && y <= map.GetUpperBound(0))
            {
                if (map[x, y] != null)
                {
                    lp.AddRange(map[x, y].GetEnemyPieces(pieceUnderDiscussion.Team));
                }
            }
        }        

        private static BorderFeatureDirection ComputeDirectionOfMovement(Gametangle previousGametangle, Gametangle gt)
        {
            UIElement uie = (UIElement)previousGametangle.Parent;
            Point from = uie.TranslatePoint(new Point(0, 0), previousGametangle);
            Point to = uie.TranslatePoint(new Point(0, 0), gt);

            if (from.X == to.X)
            {
                if (from.Y < to.Y)
                {
                    return BorderFeatureDirection.North;
                }
                else
                {
                    return BorderFeatureDirection.South;
                }
            }
            else if (from.X > to.X)
            {
                if (from.Y < to.Y)
                {
                    return BorderFeatureDirection.NorthEast;
                }
                else if (from.Y == to.Y)
                {
                    return BorderFeatureDirection.East;
                }
                else
                {
                    return BorderFeatureDirection.SouthEast;
                }
            }
            else
            {
                if (from.Y < to.Y)
                {
                    return BorderFeatureDirection.NorthWest;
                }
                else if (from.Y == to.Y)
                {
                    return BorderFeatureDirection.West;
                }
                else
                {
                    return BorderFeatureDirection.SouthWest;
                }
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (currentTeam == GameTeam.Red)
            {
                currentTeam = GameTeam.Blue;
            }
            else
            {
                currentTeam = GameTeam.Red;
            }

            if (currentTeam == startingTeam)
            {
                turnCount++;
            }

            foreach (Piece p in moves.Keys)
            {
                if (p.NeedsCombatResolution != null)
                {                    
                    int attackerOdds = GetOdds(p);

                    foreach (Piece q in p.NeedsCombatResolution)
                    {
                        int defenderOdds = GetOdds(q);
                        // remember, my enemy's enemies are my friends below
                        List<Piece> ourSupportingForces = GetAdjoiningEnemies(q.X, q.Y, q);
                        
                        foreach (Piece friend in ourSupportingForces)
                        {
                            // This will return us, as well -- so need to remove us
                            if (friend != p)
                            {
                                attackerOdds += GetOdds(friend);
                            }
                        }

                        double ratio = attackerOdds / defenderOdds;

                        int roll = r.Next(6) + 1;
                        switch (roll)
                        {
                            case 1:
                                if (ratio == 1)
                                {
                                    Info.Content = "Defender Eliminated";
                                }
                                else if (ratio == 2)
                                {
                                    Info.Content = "Defender Eliminated";
                                }
                                else if (ratio == 3)
                                {
                                    Info.Content = "Defender Eliminated";
                                }
                                else if (ratio == 4)
                                {
                                    Info.Content = "Defender Eliminated";
                                }
                                else if (ratio == 5)
                                {
                                    Info.Content = "Defender Eliminated";
                                }
                                else if (ratio == 6)
                                {
                                    Info.Content = "Defender Eliminated";
                                }
                                else if (ratio == .5)
                                {
                                    Info.Content = "Defender Back 2";
                                }
                                else if (ratio > .3 && ratio < .35)
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                else if (ratio == .25)
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                else if (ratio == .20)
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                else
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                break;
                            case 2:
                                if (ratio == 1)
                                {
                                    Info.Content = "Exchange";
                                }
                                else if (ratio == 2)
                                {
                                    Info.Content = "Exchange";
                                }
                                else if (ratio == 3)
                                {
                                    Info.Content = "Exchange";
                                }
                                else if (ratio == 4)
                                {
                                    Info.Content = "Exchange";
                                }
                                else if (ratio == 5)
                                {
                                    Info.Content = "Defender Back 4";
                                }
                                else if (ratio == 6)
                                {
                                    Info.Content = "Defender Back 5";
                                }
                                else if (ratio == .5)
                                {
                                    Info.Content = "Exchange";
                                }
                                else if (ratio > .3 && ratio < .35)
                                {
                                    Info.Content = "Attacker Back 3";
                                }
                                else if (ratio == .25)
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                else if (ratio == .20)
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                else
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                break;
                            case 3:
                                if (ratio == 1)
                                {
                                    Info.Content = "Defender Back 2";
                                }
                                else if (ratio == 2)
                                {
                                    Info.Content = "Defender Back 2";
                                }
                                else if (ratio == 3)
                                {
                                    Info.Content = "Defender Back 2";
                                }
                                else if (ratio == 4)
                                {
                                    Info.Content = "Defender Eliminated";
                                }
                                else if (ratio == 5)
                                {
                                    Info.Content = "Defender Eliminated";
                                }
                                else if (ratio == 6)
                                {
                                    Info.Content = "Defender Eliminated";
                                }
                                else if (ratio == .5)
                                {
                                    Info.Content = "Attacker Back 2";
                                }
                                else if (ratio > .3 && ratio < .35)
                                {
                                    Info.Content = "Attacker Back 3";
                                }
                                else if (ratio == .25)
                                {
                                    Info.Content = "Attacker Back 4";
                                }
                                else if (ratio == .20)
                                {
                                    Info.Content = "Attacker Back 5";
                                }
                                else
                                {
                                    Info.Content = "Attacker Back 6";
                                }
                                break;
                            case 4:
                                if (ratio == 1)
                                {
                                    Info.Content = "Attacker Back 2";
                                }
                                else if (ratio == 2)
                                {
                                    Info.Content = "Attacker Back 2";
                                }
                                else if (ratio == 3)
                                {
                                    Info.Content = "Defender Back 2";
                                }
                                else if (ratio == 4)
                                {
                                    Info.Content = "Defender Back 3";
                                }
                                else if (ratio == 5)
                                {
                                    Info.Content = "Defender Back 4";
                                }
                                else if (ratio == 6)
                                {
                                    Info.Content = "Defender Eliminated";
                                }
                                else if (ratio == .5)
                                {
                                    Info.Content = "Attacker Back 2";
                                }
                                else if (ratio > .3 && ratio < .35)
                                {
                                    Info.Content = "Attacker Back 3";
                                }
                                else if (ratio == .25)
                                {
                                    Info.Content = "Attacker Back 4";
                                }
                                else if (ratio == .20)
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                else
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                break;
                            case 5:
                                if (ratio == 1)
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                else if (ratio == 2)
                                {
                                    Info.Content = "Exchange";
                                }
                                else if (ratio == 3)
                                {
                                    Info.Content = "Exchange";
                                }
                                else if (ratio == 4)
                                {
                                    Info.Content = "Defender Back 3";
                                }
                                else if (ratio == 5)
                                {
                                    Info.Content = "Defender Eliminated";
                                }
                                else if (ratio == 6)
                                {
                                    Info.Content = "Defender Eliminated";
                                }
                                else if (ratio == .5)
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                else if (ratio > .3 && ratio < .35)
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                else if (ratio == .25)
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                else if (ratio == .20)
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                else
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                break;
                            case 6:
                                if (ratio == 1)
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                else if (ratio == 2)
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                else if (ratio == 3)
                                {
                                    Info.Content = "Defender Eliminated";
                                }
                                else if (ratio == 4)
                                {
                                    Info.Content = "Defender Eliminated";
                                }
                                else if (ratio == 5)
                                {
                                    Info.Content = "Defender Eliminated";
                                }
                                else if (ratio == 6)
                                {
                                    Info.Content = "Defender Eliminated";
                                }
                                else if (ratio == .5)
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                else if (ratio > .3 && ratio < .35)
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                else if (ratio == .25)
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                else if (ratio == .20)
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                else
                                {
                                    Info.Content = "Attacker Eliminated";
                                }
                                break;
                        }
                    }
                }
            }

            TeamName.Content = currentTeam;
            TurnCount.Content = turnCount;
            movesLeft = 5.0;
            MoveCount.Content = 5;
        }

        private int GetOdds(Piece p)
        {
            // todo: Take landscape into account
            // todo: Add non-combat pieces

            if (p.Force == Forces.Armor)
            {
                return 2;
            }
            else
            {
                return 1;
            }
        }

        private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            Process.Start("http://wpftbsw.codeplex.com/documentation");
        }
    }    
}
